﻿// <copyright file="Guard.cs" company="Lu Studio">
// Copyright (c) Lu Studio. All rights reserved.
// </copyright>
// <author>lu qi</author>
// <createTime>2021-06-19</createTime>
namespace ElfKit.Common
{
    using ElfKit.Common.Properties;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;

    /// <summary>
    /// 参数守卫.
    /// </summary>
    public static class Guard
    {
        #region NotNull

        /// <summary>
        /// 确保<paramref name="argValue"/>不为null.
        /// </summary>
        /// <param name="argValue">参数值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentNullException"><paramref name="argValue"/>is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        public static void NotNull(object argValue, string argName)
        {
            HandleArgName(argName);
            if (argValue is null)
            {
                throw new ArgumentNullException(
                    argName,
                    Localization.Format<Resources>(
                        nameof(Resources.ArgumentIsNull),
                        argName));
            }
        }

        #endregion

        #region NotNullOrWhiteSpace

        /// <summary>
        /// 确保<paramref name="argValue"/>不为null 或 string.Empty 或 WhiteSpace.
        /// </summary>
        /// <param name="argValue">参数值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        public static void NotNullOrWhiteSpace(string argValue, string argName)
        {
            HandleArgName(argName);
            if (string.IsNullOrWhiteSpace(argValue))
            {
                throw new ArgumentException(
                    Localization.Format<Resources>(
                        nameof(Resources.ArgumentIsNullOrWhiteSpace),
                        argName),
                    argName);
            }
        }

        #endregion

        #region NotNullOrEmpty

        /// <summary>
        /// 确保<paramref name="argValue"/>不为null 或 空.
        /// </summary>
        /// <param name="argValue">参数值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is null or 空.</exception>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        public static void NotNullOrEmpty(object argValue, string argName)
        {
            HandleArgName(argName);
            if (argValue is null)
            {
                throw IsNullOrEmptyException(argName);
            }

            if (argValue is IEnumerable enumerable)
            {
                IEnumerator enumerator = enumerable.GetEnumerator();
                if (!enumerator.MoveNext())
                {
                    throw IsNullOrEmptyException(argName);
                }
            }
        }

        #endregion

        #region IsEnum

        /// <summary>
        /// 确保<paramref name="argValue"/>是枚举类型.
        /// </summary>
        /// <param name="argValue">参数值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentNullException"><paramref name="argValue"/>is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        public static void IsEnum(Type argValue, string argName)
        {
            HandleArgName(argName);
            Guard.NotNull(argValue, argName);

            if (!argValue.IsEnum)
            {
                throw new ArgumentException(
                    Localization.Format<Resources>(
                        nameof(Resources.ArgumentIsNotEnum),
                        argName),
                    argName);
            }
        }

        #endregion

        #region Must

        /// <summary>
        /// <paramref name="argValue"/>必须满足<paramref name="predicate"/>委托的条件否则抛出<paramref name="exceptionFactory"/>
        /// 生成的<typeparamref name="TException"/>实例.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <typeparam name="TException">异常类型.</typeparam>
        /// <param name="argValue">参数值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="predicate"></param>
        /// <param name="exceptionFactory"></param>
        /// <exception cref="ArgumentNullException"><paramref name="argValue"/>is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="exceptionFactory"/>is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="predicate"/>is null.</exception>
        public static void Must<T, TException>(
            T argValue,
            string argName,
            Predicate<T> predicate,
            Func<string, TException> exceptionFactory)
            where TException : Exception
        {
            HandleArgName(argName);
            Guard.NotNull(predicate, nameof(predicate));
            Guard.NotNull(exceptionFactory, nameof(exceptionFactory));

            if (!predicate(argValue))
            {
                throw exceptionFactory(argName);
            }
        }

        #endregion

        #region GreaterThanZero

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(byte argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (byte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(byte? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (byte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(sbyte argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (sbyte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(sbyte? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (sbyte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(short argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (short)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(short? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (short)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(ushort argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (ushort)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(ushort? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (ushort)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(int argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, 0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(int? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, 0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(uint argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (uint)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(uint? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (uint)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(long argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, 0L);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(long? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, 0L);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(ulong argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, (ulong)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(ulong? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, (ulong)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(decimal argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, 0M);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(decimal? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, 0M);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(float argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, 0F);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(float? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, 0F);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(double argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThan, 0D);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than or equal zero.</exception>
        public static void GreaterThanZero(double? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThan, 0D);
        }

        #endregion

        #region GreaterThanOrEqualZero

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(byte argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (byte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(byte? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (byte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(sbyte argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (sbyte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(sbyte? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (sbyte)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(short argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (short)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(short? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (short)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(ushort argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (ushort)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(ushort? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (ushort)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(int argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, 0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(int? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, 0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(uint argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (uint)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(uint? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (uint)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(long argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, 0L);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(long? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, 0L);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(ulong argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, (ulong)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(ulong? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, (ulong)0);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(decimal argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, 0M);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(decimal? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, 0M);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(float argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, 0F);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(float? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, 0F);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(double argValue, string argName)
        {
            Compare(argValue, argName, ComparsionType.GreaterThanOrEqual, 0D);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值大于等于0.
        /// </summary>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is less than zero.</exception>
        public static void GreaterThanOrEqualZero(double? argValue, string argName)
        {
            Guard.NotNull(argValue, argName);
            Compare(argValue.Value, argName, ComparsionType.GreaterThanOrEqual, 0D);
        }

        #endregion

        #region Compare

        /// <summary>
        /// 保证<paramref name="argValue"/>值符合<paramref name="comparsionType"/>与<paramref name="compareValue"/>的比较逻辑.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="comparsionType"><see cref="ComparsionType"/>类型.</param>
        /// <param name="compareValue">比较值.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is invalid.</exception>
        public static void Compare<T>(T argValue, string argName, ComparsionType comparsionType, T compareValue)
            where T : IComparable<T>
        {
            Compare<T>(argValue, argName, comparsionType, compareValue, Comparer<T>.Default);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值符合<paramref name="comparsionType"/>与<paramref name="compareValue"/>的比较逻辑.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="comparsionType"><see cref="ComparsionType"/>类型.</param>
        /// <param name="compareValue">比较值.</param>
        /// <param name="comparer"><see cref="IComparer{T}"/>实例.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is invalid.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="comparer"/>is null.</exception>
        public static void Compare<T>(T argValue, string argName, ComparsionType comparsionType, T compareValue, IComparer<T> comparer)
        {
            HandleArgName(argName);
            Guard.NotNull(comparer, nameof(comparer));

            if (!ValidateComparsion(argValue, comparsionType, compareValue, comparer))
            {
                ArgumentException ex= new ArgumentException(
                    Localization.Format<Resources>(
                        nameof(Resources.ArgumentCompareInvalid),
                        argName,
                        comparsionType.GetDescription(),
                        compareValue.ToString()),
                    argName);
                ex.Data[nameof(comparsionType)] = comparsionType;
                ex.Data[nameof(compareValue)] = compareValue;
                throw ex;
            }
        }
        #endregion

        #region Between
        /// <summary>
        /// 保证<paramref name="argValue"/>值在<paramref name="min"/>与<paramref name="max"/>的范围内的逻辑.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="min"><typeparamref name="T"/>最小值.</param>
        /// <param name="max"><typeparamref name="T"/>最大值.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is invalid.</exception>
        public static void Between<T>(T argValue, string argName, T min,  T max)
            where T : IComparable<T>
        {
            Between<T>(argValue, argName, min, true, max, true);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值在<paramref name="min"/>与<paramref name="max"/>的范围内的逻辑.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="min"><typeparamref name="T"/>最小值.</param>
        /// <param name="includeMin">是否包含最小值.</param>
        /// <param name="max"><typeparamref name="T"/>最大值.</param>
        /// <param name="includeMax">是否包含最大值.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is invalid.</exception>
        public static void Between<T>(T argValue, string argName, T min, bool includeMin, T max, bool includeMax)
            where T : IComparable<T>
        {
            Between<T>(argValue, argName, min, includeMin, max, includeMax,Comparer<T>.Default);
        }

        /// <summary>
        /// 保证<paramref name="argValue"/>值在<paramref name="min"/>与<paramref name="max"/>的范围内的逻辑.
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">值.</param>
        /// <param name="argName">参数名.</param>
        /// <param name="min"><typeparamref name="T"/>最小值.</param>
        /// <param name="includeMin">是否包含最小值.</param>
        /// <param name="max"><typeparamref name="T"/>最大值.</param>
        /// <param name="includeMax">是否包含最大值.</param>
        /// <param name="comparer"><see cref="IComparer{T}"/>实例.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        /// <exception cref="ArgumentException"><paramref name="argValue"/>is invalid.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="comparer"/>is null.</exception>
        public static void Between<T>(T argValue, string argName, T min, bool includeMin, T max, bool includeMax, IComparer<T> comparer)
        {
            HandleArgName(argName);
            Guard.NotNull(comparer, nameof(comparer));

            if (!ValidateComparsion(argValue, min, includeMin, max, includeMax,comparer))
            {
                string minDescription = includeMin ? ComparsionType.GreaterThanOrEqual.GetDescription() : ComparsionType.GreaterThan.GetDescription();
                string maxDescription = includeMax ? ComparsionType.LessThanOrEqual.GetDescription() : ComparsionType.LessThan.GetDescription();
                ArgumentException ex= new ArgumentException(
                    Localization.Format<Resources>(
                        nameof(Resources.ArgumentBetweenInvalid),
                        argName,
                        minDescription,
                        min.ToString(),
                        maxDescription,
                        max.ToString()),
                    argName);
                ex.Data[nameof(min)] = min;
                ex.Data[nameof(includeMin)] = includeMin;
                ex.Data[nameof(max)] = max;
                ex.Data[nameof(includeMax)] = includeMax;
                throw ex;
            }
        }
        #endregion

        #region 内部函数

        /// <summary>
        /// 为null或空的<see cref="ArgumentException"/>实例.
        /// </summary>
        /// <param name="argName">参数名.</param>
        /// <returns><see cref="ArgumentException"/>实例.</returns>
        private static ArgumentException IsNullOrEmptyException(string argName)
        {
            throw new ArgumentException(
                Localization.Format<Resources>(
                    nameof(Resources.ArgumentIsNullOrEmpty),
                    argName),
                argName);
        }

        /// <summary>
        /// 处理参数名.
        /// </summary>
        /// <param name="argName">参数名.</param>
        /// <exception cref="ArgumentException"><paramref name="argName"/>is null or string.Empty or WhiteSpace.</exception>
        private static void HandleArgName(string argName)
        {
            if (string.IsNullOrWhiteSpace(argName))
            {
                throw new ArgumentException(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.ArgumentNameIsNullOrWhiteSpace),
                    nameof(argName));
            }
        }

        /// <summary>
        /// 验证比较
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">参数值.</param>
        /// <param name="comparsionType"><see cref="ComparsionType"/>类型.</param>
        /// <param name="compareValue">比较值.</param>
        /// <param name="comparer"><see cref="IComparer{T}"/>实例.</param>
        /// <returns>true：是 false:否.</returns>
        private static bool ValidateComparsion<T>(T argValue, ComparsionType comparsionType, T compareValue, IComparer<T> comparer)
        {
            int result = comparer.Compare(argValue, compareValue);
            return comparsionType switch
            {
                ComparsionType.Equal => result == 0,
                ComparsionType.NotEqual => result != 0,
                ComparsionType.LessThan => result < 0,
                ComparsionType.LessThanOrEqual => result <= 0,
                ComparsionType.GreaterThan => result > 0,
                ComparsionType.GreaterThanOrEqual => result >= 0,
                _ => throw new ArgumentOutOfRangeException(nameof(comparsionType)),
            };
        }

        /// <summary>
        /// 验证比较
        /// </summary>
        /// <typeparam name="T">类型.</typeparam>
        /// <param name="argValue">参数值.</param>
        /// <param name="min"><typeparamref name="T"/>最小值.</param>
        /// <param name="includeMin">是否包含最小值.</param>
        /// <param name="max"><typeparamref name="T"/>最大值.</param>
        /// <param name="includeMax">是否包含最大值.</param>
        /// <param name="comparer"><see cref="IComparer{T}"/>实例.</param>
        /// <returns>true：是 false:否.</returns>
        private static bool ValidateComparsion<T>(T argValue, T min, bool includeMin, T max, bool includeMax, IComparer<T> comparer)
        {
            int minResult = comparer.Compare(argValue, min);
            int maxResult = comparer.Compare(argValue, max);

            bool minIsValid = includeMin ? minResult >= 0 : minResult > 0;
            bool maxIsValid = includeMax ? maxResult <= 0 : maxResult < 0;
            return minIsValid && maxIsValid;
        }

        #endregion
    }
}